package com.christina.engine.execution.model;

import lombok.Getter;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 执行结果数据模型
 * 包含服务执行结果的所有相关信息
 */
@Getter
public class ExecutionResult {
    
    private final boolean success;
    private final Object resultData;
    private final String errorMessage;
    private final Throwable exception;
    private final Map<String, Object> metadata;
    private final LocalDateTime executionTime;
    private final long executionDurationMs;
    private final String executorName;
    
    private ExecutionResult(Builder builder) {
        this.success = builder.success;
        this.resultData = builder.resultData;
        this.errorMessage = builder.errorMessage;
        this.exception = builder.exception;
        this.metadata = new HashMap<>(builder.metadata);
        this.executionTime = builder.executionTime != null ? builder.executionTime : LocalDateTime.now();
        this.executionDurationMs = builder.executionDurationMs;
        this.executorName = builder.executorName;
    }
    
    // 自定义getter方法返回防御性拷贝
    public Map<String, Object> getMetadata() { 
        return new HashMap<>(metadata); 
    }
    
    // 便利方法
    public <T> T getResultData(Class<T> type) {
        if (resultData != null && type.isInstance(resultData)) {
            return type.cast(resultData);
        }
        return null;
    }
    
    public <T> T getMetadata(String key, Class<T> type) {
        Object value = metadata.get(key);
        if (value != null && type.isInstance(value)) {
            return type.cast(value);
        }
        return null;
    }
    
    public boolean hasMetadata(String key) {
        return metadata.containsKey(key);
    }
    
    public boolean isFailure() {
        return !success;
    }
    
    public boolean hasError() {
        return errorMessage != null || exception != null;
    }
    
    public String getRequestId() {
        return getMetadata("requestId", String.class);
    }
    
    public long getExecutionDuration() {
        return executionDurationMs;
    }
    
    // Builder模式
    public static class Builder {
        private boolean success = true;
        private Object resultData;
        private String errorMessage;
        private Throwable exception;
        private Map<String, Object> metadata = new HashMap<>();
        private LocalDateTime executionTime;
        private long executionDurationMs = 0;
        private String executorName;
        
        public Builder success(boolean success) {
            this.success = success;
            return this;
        }
        
        public Builder resultData(Object resultData) {
            this.resultData = resultData;
            return this;
        }
        
        public Builder errorMessage(String errorMessage) {
            this.errorMessage = errorMessage;
            return this;
        }
        
        public Builder exception(Throwable exception) {
            this.exception = exception;
            return this;
        }
        
        public Builder metadata(String key, Object value) {
            this.metadata.put(key, value);
            return this;
        }
        
        public Builder metadata(Map<String, Object> metadata) {
            this.metadata.putAll(metadata);
            return this;
        }
        
        public Builder executionTime(LocalDateTime executionTime) {
            this.executionTime = executionTime;
            return this;
        }
        
        public Builder executionDurationMs(long executionDurationMs) {
            this.executionDurationMs = executionDurationMs;
            return this;
        }
        
        public Builder executorName(String executorName) {
            this.executorName = executorName;
            return this;
        }
        
        public ExecutionResult build() {
            // 如果有异常或错误消息，自动设置为失败
            if (exception != null || errorMessage != null) {
                this.success = false;
            }
            
            return new ExecutionResult(this);
        }
    }
    
    public static Builder builder() {
        return new Builder();
    }
    
    // 静态工厂方法 - 常用结果类型
    public static ExecutionResult success(Object resultData) {
        return builder()
                .success(true)
                .resultData(resultData)
                .build();
    }
    
    public static ExecutionResult success(Object resultData, String executorName) {
        return builder()
                .success(true)
                .resultData(resultData)
                .executorName(executorName)
                .build();
    }
    
    public static ExecutionResult success(Object resultData, long executionDurationMs) {
        return builder()
                .success(true)
                .resultData(resultData)
                .executionDurationMs(executionDurationMs)
                .build();
    }
    
    public static ExecutionResult failure(String errorMessage) {
        return builder()
                .success(false)
                .errorMessage(errorMessage)
                .build();
    }
    
    public static ExecutionResult failure(String errorMessage, String executorName) {
        return builder()
                .success(false)
                .errorMessage(errorMessage)
                .executorName(executorName)
                .build();
    }
    
    public static ExecutionResult failure(Throwable exception) {
        return builder()
                .success(false)
                .exception(exception)
                .errorMessage(exception.getMessage())
                .build();
    }
    
    public static ExecutionResult failure(String errorMessage, Throwable exception) {
        return builder()
                .success(false)
                .errorMessage(errorMessage)
                .exception(exception)
                .build();
    }
    
    public static ExecutionResult failure(String errorMessage, Throwable exception, String executorName) {
        return builder()
                .success(false)
                .errorMessage(errorMessage)
                .exception(exception)
                .executorName(executorName)
                .build();
    }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ExecutionResult that = (ExecutionResult) o;
        return success == that.success &&
                executionDurationMs == that.executionDurationMs &&
                Objects.equals(resultData, that.resultData) &&
                Objects.equals(errorMessage, that.errorMessage) &&
                Objects.equals(metadata, that.metadata) &&
                Objects.equals(executorName, that.executorName);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(success, resultData, errorMessage, metadata, 
                          executionDurationMs, executorName);
    }
    
    @Override
    public String toString() {
        return "ExecutionResult{" +
                "success=" + success +
                ", executorName='" + executorName + '\'' +
                ", executionDurationMs=" + executionDurationMs +
                ", hasResultData=" + (resultData != null) +
                ", hasError=" + hasError() +
                ", metadataCount=" + metadata.size() +
                '}';
    }
}